package com.group.project.hrms.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.group.project.hrms.entity.ContactBasic;
import com.group.project.hrms.entity.DingClockRecord;
import com.group.project.hrms.entity.ResultEntity.RangeClockEntity;
import com.group.project.hrms.entity.ResultEntity.ResultEntity;
import com.group.project.hrms.service.IContactBasicService;
import com.group.project.hrms.service.IDingClockRecordService;
import com.group.project.hrms.utils.*;
import javafx.beans.binding.ObjectExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
public class ClockRecordController {

    @Autowired
    private IContactBasicService iContactBasicService;

    @Autowired
    private DingAccessUtils dingAccessUtils;

    @Autowired
    private ProgressUtil progressUtil;

    @Autowired
    private IDingClockRecordService iDingClockRecordService;

    @Autowired
    private BasicInfoUtil basicInfoUtil;

    @Autowired
    private LogUtil logUtil;

    @Autowired
    private AttendanceUtil attendanceUtil;


    /**
     * 该方法将接受前端传入的月份，从钉钉服务器中获取该月份全员的打卡记录并存储于本地数据库中 DingClockRecord
     * @param map 前端传入的月份
     * @param request http请求
     * @return 包含同步结果的标准返回值对象
     */
    @RequestMapping("/basic/doSyncClockFromDing")
    @ResponseBody
    public ResultEntity doSyncClockFromDing(@RequestBody Map map, HttpServletRequest request){
        ResultEntity resultEntity = new ResultEntity();
        Date date = new Date();
        Object staffName = request.getAttribute("staffName");
        List<DingClockRecord> records = new ArrayList<>();
        //获取当前年月日信息
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);

        //获取用户传入的年月日信息
        Object obj = map.get("month");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try{
            calendar.setTime(sdf.parse(obj.toString().substring(0,10)));
        }catch (ParseException pe){
            pe.printStackTrace();
            resultEntity.setCode("F");
            resultEntity.setMsg("传入的月份信息有误");
            return resultEntity;
        }

        int yearSelected = calendar.get(Calendar.YEAR);
        int monthSelected = calendar.get(Calendar.MONTH) + 1;
        int totalDaysSelected = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        System.out.println("用户传入的日期经过转换为：" + yearSelected + "-" + monthSelected + "-" + totalDaysSelected);

        //获取所有通讯里ID
        List<String> idList = dingAccessUtils.doGetUserIds(iContactBasicService.selectAllContactBasic());

        System.out.println("本地通讯里中包含离职的人员，一共有：" + idList.size());

        //获取所有id下的指定月份的所有打卡记录
        if(idList.size() == 0){
            resultEntity.setCode("F");
            resultEntity.setMsg("无人员信息");
            return resultEntity;
        }else{

            int i = idList.size() / 50; //钉钉规定，该接口的查询每次传递的人员不得超过50个
            int j = idList.size() % 50;

            for (int k = 0; k < (i == 0 ? 1 : i); k++) {
                List<String> targetList = new ArrayList<>();
                if(i == 0){
                    targetList = idList;
                }
                if(i != 0){
                    targetList = idList.subList(k*50, k*50 + 50);
                    if(k == i - 1 && j != 0){
                        List<String> leftIds = idList.subList((k + 1)*50, (k + 1)*50 + j);
                        records.addAll(this.getDingClockRecord(year, month, day, yearSelected, monthSelected, totalDaysSelected, leftIds));
                    }
                }
                records.addAll(this.getDingClockRecord(year, month, day, yearSelected, monthSelected, totalDaysSelected, targetList));
                ProgressUtil.percent = ProgressUtil.percent >= 10 ? 10 : ProgressUtil.percent + k*2;
            }
        }
        System.out.println("从钉钉中查询到：" + records.size() + " 条记录");
        //删除指定月份在本地数据库的所有打卡记录
        String pointDate = yearSelected + (monthSelected == 10 || monthSelected == 11 || monthSelected == 12 ? "-" + monthSelected : "-0" + monthSelected);
        System.out.println("即将从数据库中查询指定的月份为：" + pointDate);
        List<DingClockRecord> localRecords = iDingClockRecordService.selectDingClockRecordByDate(pointDate);
        System.out.println("共查询到 ：" + localRecords.size() + " 条本地数据");

        ProgressUtil.percent = 49;

        int insertCount = 0;
        if(localRecords.size() != 0){
            Map<String, List<DingClockRecord>> clockMapByUserId = attendanceUtil.getDingClockRecordMap(localRecords);
            //如果本地记录不为空，则进行对比，若钉钉中的记录本地不存在，则执行插入，否则忽略即可
            for (DingClockRecord cr : records
                 ) {
                List<DingClockRecord> userRecords = clockMapByUserId.get(cr.getUserid());
                if(null != userRecords){
                    boolean isContain = false;
                    for (DingClockRecord re : userRecords
                         ) {
                        if(cr.getUserchecktime().getTime() == re.getUserchecktime().getTime()){
                            isContain = true;
                        }
                    }
                    if(!isContain){
                        insertCount = insertCount + iDingClockRecordService.insertDingClockRecord(cr);
                    }
                }else {
                    insertCount = insertCount + iDingClockRecordService.insertDingClockRecord(cr);
                }
            }
        }else {
            //如果本地月度打卡记录为0，则向数据库插入全部钉钉数据
            insertCount = iDingClockRecordService.insertDingClockRecords(records);
        }

        //int deletedCount = iDingClockRecordService.deleteDingClockRecordByMonth(pointDate);
        //System.out.println("删除本地数据共计：" + deletedCount);

        //ProgressUtil.percent = 59;

        //向数据库插入数据
        //int insertCount = iDingClockRecordService.insertDingClockRecords(records);

        ProgressUtil.percent = 99;

        System.out.println("共计插入了：" + insertCount + " 条打卡记录");

        List<Integer> resList = new ArrayList<>();
        resList.add(insertCount);
        logUtil.insertSystemEventLog(staffName.toString(), date, " 同步了" + month + "的打卡记录", "考勤");
        resultEntity.setCode("S");
        resultEntity.setDataList(resList);
        resultEntity.setMsg("同步完成");
        return resultEntity;
    }


    /**
     * 该方法主要用于判断年月日的几种情况：当年当月、当年非当月、跨年
     * @param year
     * @param month
     * @param day
     * @param yearSelected
     * @param monthSelected
     * @param totalDaysSelected
     * @param targetList
     * @return
     */
    private List<DingClockRecord> getDingClockRecord(int year, int month, int day, int yearSelected, int monthSelected, int totalDaysSelected, List<String> targetList){
        if(yearSelected == year){
            if(monthSelected == month){ //当年当月的情况，需要考虑天数的计算
                return this.getDingClockRecordBySelectedMonth(yearSelected, monthSelected, day, targetList);
            }else if(monthSelected < month && (month - monthSelected) < 6){ //当年非当月情况，但必须满足月份间隔不大于6个月
                return this.getDingClockRecordBySelectedMonth(yearSelected, monthSelected, totalDaysSelected, targetList);
            }
        }else if(yearSelected < year && (year - yearSelected) == 1 && (12 - monthSelected + month) < 6){ //跨年且只能跨一年的情况，需满足月份间隔不大于6个月
            return this.getDingClockRecordBySelectedMonth(yearSelected, monthSelected, totalDaysSelected, targetList);
        }
        return new ArrayList<>();
    }

    /**
     * 从钉钉中获取打卡记录，每次最大传入50人和7天
     * @param year
     * @param month
     * @param totalDays
     * @param userIds
     * @return
     */
    private List<DingClockRecord> getDingClockRecordBySelectedMonth(int year, int month, int totalDays, List<String> userIds){
        List<DingClockRecord> list = new ArrayList<>();
        String checkFrom = year + "-" + month + "-";
        String timeFormatStart = " 00:00:00";
        String timeFormatEnd = " 23:59:59";
        try{
            if(totalDays <= 7){ //1-7
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 1 + timeFormatStart, checkFrom + totalDays + timeFormatEnd));
            }else if(totalDays <= 14){ //8-14
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 1 + timeFormatStart, checkFrom + 7 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 8 + timeFormatStart, checkFrom + totalDays + timeFormatEnd));
            }else if(totalDays <= 21){ //15-21
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 1 + timeFormatStart, checkFrom + 7 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 8 + timeFormatStart, checkFrom + 14 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 15 + timeFormatStart, checkFrom + totalDays + timeFormatEnd));
            }else if(totalDays <= 28){ //22-28
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 1 + timeFormatStart, checkFrom + 7 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 8 + timeFormatStart, checkFrom + 14 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 15 + timeFormatStart, checkFrom + 21 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 22 + timeFormatStart, checkFrom + totalDays + timeFormatEnd));
            }else{ //29以后
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 1 + timeFormatStart, checkFrom + 7 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 8 + timeFormatStart, checkFrom + 14 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 15 + timeFormatStart, checkFrom + 21 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 22 + timeFormatStart, checkFrom + 28 + timeFormatEnd));
                list.addAll(dingAccessUtils.doGetDingClockRecord(userIds, checkFrom + 29 + timeFormatStart, checkFrom + totalDays + timeFormatEnd));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        //System.out.println("进入这里了：" + list.size());
        return list;
    }

    /**
     * 该方法接收前端传入的时间段数据，向数据库查询一段时间内的原始打卡记录
     * @param map 前端传入的时间段数据
     * @param request http请求
     * @return 标准返回值对象
     */
    @RequestMapping("/basic/getDingClockRecordByRangeDate")
    @ResponseBody
    public ResultEntity getDingClockRecordByRangeDate(@RequestBody Map map, HttpServletRequest request){
        ResultEntity resultEntity = new ResultEntity();
        List<DingClockRecord> clockRecords;
        if(null != map){
            Object rangeDate = map.get("rangeDate");
            try{
                JSONArray dateArray = JSON.parseArray(JSON.toJSONString(rangeDate));
                String startDate = dateArray.getString(0);
                String endDate = dateArray.getString(1);
                clockRecords = iDingClockRecordService.selectDingClockRecordByRangeDate(startDate, endDate);
            }catch (Exception e){
                e.printStackTrace();
                resultEntity.setCode("F");
                resultEntity.setMsg("查询失败");
                return resultEntity;
            }
            if(null != clockRecords && clockRecords.size() != 0){
                Map<String, ContactBasic> contactBasicMap = basicInfoUtil.doGetContactMap(iContactBasicService.selectAllContactBasic());
                List<RangeClockEntity> resultList = new ArrayList<>();
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                for (int i = 0; i < clockRecords.size(); i++) {
                    DingClockRecord record = clockRecords.get(i);
                    ContactBasic contactBasic = contactBasicMap.get(record.getUserid());
                    RangeClockEntity rangeClockEntity = new RangeClockEntity();
                    rangeClockEntity.setKey(i + 1);
                    rangeClockEntity.setStaffName(contactBasic.getStaffName());
                    rangeClockEntity.setJobNumber(contactBasic.getStaffId());
                    rangeClockEntity.setJobTitle(contactBasic.getTitle());
                    rangeClockEntity.setCheckTime(format.format(record.getUserchecktime()).substring(0,19));
                    resultList.add(rangeClockEntity);
                }
                resultEntity.setCode("S");
                resultEntity.setMsg("Success");
                resultEntity.setDataList(resultList);
                return resultEntity;
            }else{
                resultEntity.setCode("F");
                resultEntity.setMsg("该日期范围内无打卡记录");
                return resultEntity;
            }
        }
        resultEntity.setCode("F");
        resultEntity.setMsg("查询失败");
        return resultEntity;
    }




}
